#include "jrpc.h"
#include <stdlib.h>
#include <string.h>

// 定义方法注册表的最大大小
#define MAX_METHODS 32

// 方法结构体
typedef struct {
    char* name;
    jrpc_proc_t proc;
    void* data;
} jrpc_method_t;

// 方法注册表
static jrpc_method_t g_methods[MAX_METHODS];
static int g_method_count = 0;

cJSON* jrpc_create_request(const char *method, cJSON *params, cJSON *id) {
    cJSON* request = cJSON_CreateObject();
    if (!request) {
        return NULL;
    }
    
    // 添加JSON-RPC版本
    cJSON_AddStringToObject(request, "jsonrpc", JRPC_VERSION);
    
    // 添加方法名
    if (method) {
        cJSON_AddStringToObject(request, "method", method);
    }
    
    // 添加参数（可选）
    if (params) {
        cJSON_AddItemToObject(request, "params", params);
    }
    
    // 添加ID（可选，如果为NULL则为通知）
    if (id) {
        cJSON_AddItemToObject(request, "id", id);
    }
    
    return request;
}

cJSON* jrpc_create_response(const cJSON* result, const cJSON* error, const cJSON* id) {
    cJSON* response = cJSON_CreateObject();
    if (!response) {
        return NULL;
    }
    
    // 添加JSON-RPC版本
    cJSON_AddStringToObject(response, "jsonrpc", JRPC_VERSION);
    
    // 添加result或error（必须有一个）
    if (result) {
        cJSON_AddItemToObject(response, "result", cJSON_Duplicate(result, 1));
    }
    
    if (error) {
        cJSON_AddItemToObject(response, "error", cJSON_Duplicate(error, 1));
    }
    
    // 添加ID
    if (id) {
        cJSON_AddItemToObject(response, "id", cJSON_Duplicate(id, 1));
    } else {
        cJSON_AddNullToObject(response, "id");
    }
    
    return response;
}

cJSON* jrpc_create_error_response(int code, const char *message, const cJSON* id) {
    cJSON* error = cJSON_CreateObject();
    if (!error) {
        return NULL;
    }
    
    // 添加错误代码
    cJSON_AddNumberToObject(error, "code", code);
    
    // 添加错误消息
    if (message) {
        cJSON_AddStringToObject(error, "message", message);
    }
    
    // 创建完整的错误响应
    cJSON* response = jrpc_create_response(NULL, error, id);
    cJSON_Delete(error);
    
    return response;
}

int jrpc_register_method(const char* name, jrpc_proc_t proc, void* data) {
    // 检查参数
    if (!name || !proc) {
        return -1;
    }
    
    // 检查是否已达到最大方法数
    if (g_method_count >= MAX_METHODS) {
        return -1;
    }
    
    // 检查方法是否已注册
    for (int i = 0; i < g_method_count; i++) {
        if (strcmp(g_methods[i].name, name) == 0) {
            return -1; // 方法已存在
        }
    }
    
    // 注册新方法
    g_methods[g_method_count].name = strdup(name);
    g_methods[g_method_count].proc = proc;
    g_methods[g_method_count].data = data;
    g_method_count++;
    
    return 0; // 成功
}

int jrpc_unregister_method(const char* name) {
    // 检查参数
    if (!name) {
        return -1;
    }
    
    // 查找方法
    for (int i = 0; i < g_method_count; i++) {
        if (strcmp(g_methods[i].name, name) == 0) {
            // 释放方法名内存
            free(g_methods[i].name);
            
            // 将后续方法向前移动
            for (int j = i; j < g_method_count - 1; j++) {
                g_methods[j] = g_methods[j + 1];
            }
            
            g_method_count--;
            return 0; // 成功
        }
    }
    
    return -1; // 方法未找到
}

cJSON* jrpc_invoke_method(cJSON* request) {
    // 检查参数
    if (!request) {
        return jrpc_create_error_response(JRPC_INVALID_REQUEST, "Invalid request", NULL);
    }
    
    // 检查是否为有效的JSON对象
    if (!cJSON_IsObject(request)) {
        return jrpc_create_error_response(JRPC_INVALID_REQUEST, "Invalid request", NULL);
    }
    
    // 检查jsonrpc版本
    cJSON* jsonrpc = cJSON_GetObjectItem(request, "jsonrpc");
    if (!jsonrpc || !cJSON_IsString(jsonrpc) || strcmp(cJSON_GetStringValue(jsonrpc), JRPC_VERSION) != 0) {
        return jrpc_create_error_response(JRPC_INVALID_REQUEST, "Invalid request", NULL);
    }
    
    // 获取方法名
    cJSON* method = cJSON_GetObjectItem(request, "method");
    if (!method || !cJSON_IsString(method)) {
        return jrpc_create_error_response(JRPC_INVALID_REQUEST, "Invalid request", NULL);
    }
    
    // 获取ID（可选）
    cJSON* id = cJSON_GetObjectItem(request, "id");
    
    // 查找并调用方法
    for (int i = 0; i < g_method_count; i++) {
        if (strcmp(g_methods[i].name, cJSON_GetStringValue(method)) == 0) {
            // 调用方法处理函数
            cJSON* response = g_methods[i].proc(g_methods[i].data, request);
            
            // 如果方法返回NULL且有ID，则创建默认响应
            if (!response && id) {
                cJSON* result = cJSON_CreateNull();
                response = jrpc_create_response(result, NULL, id);
                cJSON_Delete(result);
            }
            
            return response;
        }
    }
    
    // 方法未找到
    return jrpc_create_error_response(JRPC_METHOD_NOT_FOUND, "Method not found", id);
}